"""
API错误处理装饰器和工具函数
API error handling decorators and utility functions
"""

import functools
import logging
import traceback
from typing import Any, Callable, Dict

from fastapi import HTTPException
from fastapi.responses import JSONResponse

from .exceptions import (
    ConfigurationError,
    DataParsingError,
    FileProcessingError,
    OptimizationError,
    ResourceConstraintError,
    SchedulerError,
    ValidationError,
)

# 配置日志记录器
logger = logging.getLogger(__name__)


def handle_scheduler_errors(func: Callable) -> Callable:
    """
    API错误处理装饰器
    Decorator for handling scheduler errors in API endpoints
    """

    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        try:
            return await func(*args, **kwargs)
        except SchedulerError as e:
            logger.error(
                f"Scheduler error in {func.__name__}: {e.message}",
                extra={"error_code": e.error_code, "suggestions": e.suggestions},
            )
            return create_error_response(e)
        except ValueError as e:
            logger.error(f"Value error in {func.__name__}: {str(e)}")
            validation_error = ValidationError(f"参数值错误: {str(e)}")
            return create_error_response(validation_error)
        except FileNotFoundError as e:
            logger.error(f"File not found in {func.__name__}: {str(e)}")
            file_error = FileProcessingError(f"文件未找到: {str(e)}")
            return create_error_response(file_error)
        except Exception as e:
            logger.error(
                f"Unexpected error in {func.__name__}: {str(e)}",
                extra={"traceback": traceback.format_exc()},
            )
            system_error = SchedulerError(
                f"系统内部错误: {str(e)}",
                "INTERNAL_ERROR",
                ["请联系系统管理员", "检查系统日志获取详细信息"],
            )
            return create_error_response(system_error, status_code=500)

    return wrapper


def handle_sync_scheduler_errors(func: Callable) -> Callable:
    """
    同步函数的错误处理装饰器
    Decorator for handling scheduler errors in synchronous functions
    """

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except SchedulerError as e:
            logger.error(
                f"Scheduler error in {func.__name__}: {e.message}",
                extra={"error_code": e.error_code, "suggestions": e.suggestions},
            )
            raise e
        except ValueError as e:
            logger.error(f"Value error in {func.__name__}: {str(e)}")
            raise ValidationError(f"参数值错误: {str(e)}")
        except FileNotFoundError as e:
            logger.error(f"File not found in {func.__name__}: {str(e)}")
            raise FileProcessingError(f"文件未找到: {str(e)}")
        except Exception as e:
            logger.error(
                f"Unexpected error in {func.__name__}: {str(e)}",
                extra={"traceback": traceback.format_exc()},
            )
            raise SchedulerError(
                f"系统内部错误: {str(e)}",
                "INTERNAL_ERROR",
                ["请联系系统管理员", "检查系统日志获取详细信息"],
            )

    return wrapper


def create_error_response(
    error: SchedulerError, status_code: int = 400
) -> JSONResponse:
    """
    创建标准化的错误响应
    Create standardized error response
    """
    error_data = {
        "success": False,
        "error": error.to_dict(),
        "timestamp": get_current_timestamp(),
    }

    return JSONResponse(status_code=status_code, content=error_data)


def get_current_timestamp() -> str:
    """获取当前时间戳"""
    from datetime import datetime

    return datetime.now().isoformat()


def log_api_request(endpoint: str, params: Dict[str, Any] = None):
    """记录API请求日志"""
    logger.info(f"API request to {endpoint}", extra={"params": params or {}})


def log_api_response(endpoint: str, success: bool, duration: float = None):
    """记录API响应日志"""
    logger.info(
        f"API response from {endpoint}",
        extra={"success": success, "duration_ms": duration},
    )


def validate_required_fields(data: Dict[str, Any], required_fields: list) -> None:
    """
    验证必需字段
    Validate required fields in data
    """
    missing_fields = []
    for field in required_fields:
        if field not in data or data[field] is None:
            missing_fields.append(field)

    if missing_fields:
        raise ValidationError(
            f"缺少必需字段: {', '.join(missing_fields)}",
            field_name=missing_fields[0] if len(missing_fields) == 1 else None,
        )


def validate_positive_integer(value: Any, field_name: str) -> int:
    """
    验证正整数
    Validate positive integer value
    """
    try:
        int_value = int(value)
        if int_value <= 0:
            raise ValidationError(
                f"字段'{field_name}'必须是正整数，当前值: {value}",
                field_name=field_name,
                field_value=value,
            )
        return int_value
    except (ValueError, TypeError):
        raise ValidationError(
            f"字段'{field_name}'必须是整数，当前值: {value}",
            field_name=field_name,
            field_value=value,
        )


def validate_float_range(
    value: Any, field_name: str, min_val: float = None, max_val: float = None
) -> float:
    """
    验证浮点数范围
    Validate float value within range
    """
    try:
        float_value = float(value)

        if min_val is not None and float_value < min_val:
            raise ValidationError(
                f"字段'{field_name}'不能小于{min_val}，当前值: {value}",
                field_name=field_name,
                field_value=value,
            )

        if max_val is not None and float_value > max_val:
            raise ValidationError(
                f"字段'{field_name}'不能大于{max_val}，当前值: {value}",
                field_name=field_name,
                field_value=value,
            )

        return float_value
    except (ValueError, TypeError):
        raise ValidationError(
            f"字段'{field_name}'必须是数字，当前值: {value}",
            field_name=field_name,
            field_value=value,
        )


class ErrorContext:
    """错误上下文管理器，用于收集和报告详细的错误信息"""

    def __init__(self, operation: str):
        self.operation = operation
        self.context_data = {}

    def add_context(self, key: str, value: Any):
        """添加上下文信息"""
        self.context_data[key] = value

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type and issubclass(exc_type, SchedulerError):
            # 为异常添加上下文信息
            if hasattr(exc_val, "suggestions"):
                exc_val.suggestions.append(f"操作上下文: {self.operation}")
                for key, value in self.context_data.items():
                    exc_val.suggestions.append(f"{key}: {value}")
        return False
